package top.ply.manageservice.service.impl;

import com.auth0.jwt.JWT;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import top.ply.common_unit.entity.RespEntity;
import top.ply.common_unit.global_resp.RespUtil;
import top.ply.common_unit.token.JWTUtil;
import top.ply.manageservice.dao.ManagerMapper;
import top.ply.manageservice.pojo.Manager;
import top.ply.manageservice.service.ManagerService;

import java.util.HashMap;
import java.util.Map;

@Service
public class ManagerServiceImpl implements ManagerService {

    @Autowired
    ManagerMapper managerMapper;

    @Value("${managerservice.token.secretKey}")
    private String tokenSecretKey;

    @Value("${managerservice.token.expireTime}")
    private Long tokenExpireTime;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    AuthenticationManager authenticationManager;

    public static final String payloadManagerIDKey = "managerID";

    @Override
    public boolean verifyToken(String token) {
        return !JWTUtil.isExpire(token, tokenSecretKey);
    }

    @Override
    public String generateToken(String managerID) {
        Map<String, String> payload = new HashMap<>();
        payload.put(payloadManagerIDKey, managerID);
        return JWTUtil.createToken(payload, tokenSecretKey, tokenExpireTime);
    }

    @Override
    public Manager getManagerFromToken(String token) {
        if (!verifyToken(token)) {
            return null;
        } else {
            Map<String, String> payload = JWTUtil.getPayload(token, tokenSecretKey);
            String managerID = payload.get(payloadManagerIDKey);
            return managerMapper.getManagerByID(managerID);
        }
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return managerMapper.getManagerByUsername(username);
    }

    public RespEntity login(String username, String password) {
        String encodedPassword = passwordEncoder.encode(password);
        Manager manager = managerMapper.getManagerByUsername(username);
        String savedPassword = manager.getPassword();
        if (savedPassword.equals(encodedPassword)) {
            Map<String, String> payload = new HashMap<>();
            payload.put(payloadManagerIDKey, manager.getManagerID());
            String token = JWTUtil.createToken(payload, tokenSecretKey, tokenExpireTime);
            Map<String, Object> tokenMap = new HashMap<>(1);
            tokenMap.put("token", token);

            saveTokenToSecurity(manager);
            return RespUtil.baseSuccess(tokenMap);
        } else {
            return RespUtil.userPasswordError();
        }
    }

    private void saveTokenToSecurity(Manager manager) {
        UsernamePasswordAuthenticationToken upToken =
                new UsernamePasswordAuthenticationToken(manager.getUsername(), manager.getPassword(), manager.getAuthorities());
        Authentication authentication = authenticationManager.authenticate(upToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    public RespEntity addManager(Manager manager) {
        String managerID = manager.getManagerID();
        Manager dbManager = managerMapper.getManagerByID(managerID);
        if (dbManager != null) {
            return RespUtil.conflictError();
        } else {
            int add = managerMapper.addManager(manager);
            return add > 0 ? RespUtil.baseSuccess() : RespUtil.baseFail();
        }
    }
}
